package com.sun.umbrella.filter;

import com.sun.core.enums.BaseErrorEnum;
import com.sun.core.ex.BusinessCheckFailException;
import com.sun.umbrella.enums.ReloadStatusEnum;
import com.sun.umbrella.remote.RemoteService;
import lombok.extern.slf4j.Slf4j;
import org.apache.shiro.mgt.SecurityManager;
import org.apache.shiro.spring.web.ShiroFilterFactoryBean;
import org.apache.shiro.web.filter.mgt.FilterChainManager;
import org.apache.shiro.web.filter.mgt.FilterChainResolver;
import org.apache.shiro.web.mgt.WebSecurityManager;
import org.apache.shiro.web.servlet.AbstractShiroFilter;
import org.springframework.beans.factory.BeanInitializationException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;


/**
 * @author Jay
 * @version v1.0
 * @description shiro的Web过滤器
 * @date 2017-12-03 21:16
 */

@Slf4j
public class UmbrellaFilterFactoryBean extends ShiroFilterFactoryBean {

    @Autowired
    private RemoteService remoteService;

    @Value("${sys.id}")
    private Integer sysId;

    @Value("${filter.enable}")
    private Boolean enableFilter;

    @Override
    protected AbstractShiroFilter createInstance() throws Exception {

        log.debug("Creating Shiro Filter instance.");

        SecurityManager securityManager = getSecurityManager();
        if (securityManager == null) {
            throw new BeanInitializationException("SecurityManager property must be set.");
        }

        if (!(securityManager instanceof WebSecurityManager)) {
            throw new BeanInitializationException("The security manager does not implement the WebSecurityManager interface.");
        }

        FilterChainManager manager = createFilterChainManager();

        UmbrellaPathMatchingFilterChainResolver chainResolver = null;
        if (enableFilter) {
            // 第一次初始化实例的时候，需要重新加载过滤器，所以先重置状态为需要加载过滤器
            if (!remoteService.resetReloadFilterStatus(sysId, ReloadStatusEnum.NEED_RELOAD.getKey())){
                throw new BusinessCheckFailException(BaseErrorEnum.BNS_CHK_ERROR.getCode(),"重置是否需要加载过滤器的状态失败");
            }
            chainResolver = new UmbrellaPathMatchingFilterChainResolver(sysId, enableFilter, remoteService);
            chainResolver.setFilterChainManager(manager);
        }
        return new ShiroFilter((WebSecurityManager) securityManager, chainResolver);
    }

    private static final class ShiroFilter extends AbstractShiroFilter {

        protected ShiroFilter(WebSecurityManager webSecurityManager, FilterChainResolver resolver) {
            super();
            if (webSecurityManager == null) {
                throw new IllegalArgumentException("WebSecurityManager property cannot be null.");
            }
            setSecurityManager(webSecurityManager);
            if (resolver != null) {
                setFilterChainResolver(resolver);
            }
        }
    }

}
